#include "Node.h"
#include "Renderer.h"
#include "Drawable.h"
#include "DXMgr.h"
#include "RenderParams.h"
#include "Octree.h"

Node::Node()
: m_hasChildren(false)
, m_pChildNodes(NULL)
{

}
Node::~Node()
{
	//Clean up child nodes
	for(std::vector<Node*>::iterator iter = m_pChildNodes.begin(); iter != m_pChildNodes.end(); iter++)
	{
		Node* pElem = *iter;
		if(pElem)
		{
			delete pElem;
			pElem = NULL;
		}
	}
	m_pChildNodes.clear();

	//Clear the list of drawables
	m_pDrawableObjectList.clear();
}
Node::Node(int a_max, AABB* a_aabb)
: m_hasChildren(false)
, m_pChildNodes(NULL)
{
	//Set the max number of objects
	m_maxObjects = a_max;

	m_aabb = *a_aabb;
}
Node::Node(int a_max, AABB* a_aabb, Renderer::DrawableObjectList* a_pDrawable)
: m_hasChildren(false)
, m_pChildNodes(NULL)
{
	//Set the max number of objects
	m_maxObjects = a_max;

	m_aabb = *a_aabb;

	//Attempt to add the drawable object list to this node - the list is drawn from the parent node which no longer owns it
	if(a_pDrawable != NULL)
	{
		AddDrawables(a_pDrawable);
	}
}
void Node::ConvertToBranch()
{
	//Get the width of the new cube (half the width of the parent node)
	float width = (m_aabb.GetMax().x - m_aabb.GetMin().x) / 2;
	D3DXVECTOR3 center = m_aabb.GetMax() - D3DXVECTOR3(width, width, width);

	//Bottom left front cube
	Node* newNode1 = new Node(m_maxObjects, &AABB(m_aabb.GetMin(), center), &m_pDrawableObjectList);
	m_pChildNodes.push_back(newNode1);
	//Bottom left back cube
	Node* newNode2 = new Node(m_maxObjects, &AABB(D3DXVECTOR3(m_aabb.GetMin().x, m_aabb.GetMin().y, m_aabb.GetMin().z + width), D3DXVECTOR3(center.x, center.y, center.z + width)), &m_pDrawableObjectList);
	m_pChildNodes.push_back(newNode2);
	//Bottom right front cube
	Node* newNode3 = new Node(m_maxObjects, &AABB(D3DXVECTOR3(m_aabb.GetMin().x + width, m_aabb.GetMin().y, m_aabb.GetMin().z), D3DXVECTOR3(center.x + width, center.y, center.z)), &m_pDrawableObjectList);
	m_pChildNodes.push_back(newNode3);
	//Bottom right back cube
	Node* newNode4 = new Node(m_maxObjects, &AABB(D3DXVECTOR3(m_aabb.GetMin().x + width, m_aabb.GetMin().y, m_aabb.GetMin().z + width), D3DXVECTOR3(center.x + width, center.y, center.z + width)), &m_pDrawableObjectList);
	m_pChildNodes.push_back(newNode4);

	//Top left front cube
	Node* newNode5 = new Node(m_maxObjects, &AABB(D3DXVECTOR3(m_aabb.GetMin().x, m_aabb.GetMin().y + width, m_aabb.GetMin().z), D3DXVECTOR3(center.x, center.y + width, center.z)), &m_pDrawableObjectList);
	m_pChildNodes.push_back(newNode5);
	//Top left back cube
	Node* newNode6 = new Node(m_maxObjects, &AABB(D3DXVECTOR3(m_aabb.GetMin().x, m_aabb.GetMin().y + width, m_aabb.GetMin().z + width), D3DXVECTOR3(center.x, center.y + width, center.z + width)), &m_pDrawableObjectList);
	m_pChildNodes.push_back(newNode6);
	//Top right front cube
	Node* newNode7 = new Node(m_maxObjects, &AABB(D3DXVECTOR3(m_aabb.GetMin().x + width, m_aabb.GetMin().y + width, m_aabb.GetMin().z), D3DXVECTOR3(center.x + width, center.y + width, center.z)), &m_pDrawableObjectList);
	m_pChildNodes.push_back(newNode7);
	//Top right back cube
	Node* newNode8 = new Node(m_maxObjects, &AABB(center, m_aabb.GetMax()), &m_pDrawableObjectList);
	m_pChildNodes.push_back(newNode8);

	//Swap type
	m_hasChildren = true;

	//Clear the drawable list
	m_pDrawableObjectList.clear();
}
bool Node::HasChildren()
{
	return m_hasChildren;
}
void Node::AddDrawables(Renderer::DrawableObjectList* a_pDrawable)
{
	//Iterate through the list of drawable objects
	for(Renderer::DrawableObjectList::iterator iter = a_pDrawable->begin(); iter != a_pDrawable->end(); iter++)
	{
		Drawable* pElem = *iter;

		D3DXVECTOR3 pos = pElem->GetPos();

		D3DXVECTOR3 minBound = pElem->GetAABB().GetMin();
		D3DXVECTOR3 maxBound = pElem->GetAABB().GetMax();

		//Check to see if the drawable object overlaps the node at all
		if(pos.x + maxBound.x > m_aabb.GetMin().x)
		{
			//Inside left wall - Because of the way D3DXComputeBoundingBox() works,
			//the left side of the bounding box is a negative number, so add it, not subtract
			if(pos.x + minBound.x < m_aabb.GetMax().x)
			{
				//Inside top wall
				if(pos.y + maxBound.y > m_aabb.GetMin().y)
				{
					//Inside bottom wall - Because of the way D3DXComputeBoundingBox() works,
					//the bottom side of the bounding box is a negative number, so add it, not subtract
					if(pos.y + minBound.y < m_aabb.GetMax().y)
					{		
						//Inside back wall
						if(pos.z + maxBound.z > m_aabb.GetMin().z)
						{
							//Inside front wall - Because of the way D3DXComputeBoundingBox() works,
							//the front side of the bounding box is a negative number, so add it, not subtract
							if(pos.z + minBound.z < m_aabb.GetMax().z)							
							{
								//If it makes it here, it is overlapping the node, add it to this nodes object list
								m_pDrawableObjectList.push_back(pElem);
							}
						}
					}
				}
			}
		}
	}
}